﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace AzaEngine
{
    public enum ReplaceInternalComponents
    {
        None = 0,
        SimpleReplace,
        RegExp,
        RemoveSpaces,
        Mask
    }


    public class ReplaceEngine
    {
        public ReplaceEngine()
        {
            SetInternalComponents();
        }

        // Define os componentes (funções) internos de ReplaceEngine
        // Exemplo de alguns componentes básicos:
        // Substituir: Susbstitui uma lista de caracteres ou substrings por uma outra
        // Remove Múltiplos: Remove multiplos espaços em uma string, deixando apenas espaços simples
        private void SetInternalComponents()
        {
            // --- SimpleReplace ------------------------
            Component comp = new Component(ReplaceInternalComponents.SimpleReplace, ComponentType.Replace, "Substitui uma lista texto");
            comp.SetParameter(1, ComponentParameterType.String, "Lista de texto separados por '|'");
            comp.SetParameter(2, ComponentParameterType.String, "Texto a ser substituído");
            comp.SetParameter(3, ComponentParameterType.Bool, "Ignorar maisúsculas e minúsculas?");
            
            comp.Parameters[3].SetDefaultValue(true);
            Engine.Components.Add(comp);

            // --- RegExp -------------------------
            Component comp2 = new Component(ReplaceInternalComponents.RegExp, ComponentType.Replace, "Substituição com base em expressão regular");
            comp2.SetParameter(1, ComponentParameterType.String, "Expressão Regular");
            comp2.SetParameter(2, ComponentParameterType.String, "Texto a ser substituído");
            comp2.SetParameter(3, ComponentParameterType.Bool, "Ignorar maisúsculas e minúsculas?");
            comp2.Parameters[3].SetDefaultValue(true);
            Engine.Components.Add(comp2);

            // --- RemoveSpaces -------------------------
            Engine.Components.AddInternal(ReplaceInternalComponents.RemoveSpaces, ComponentType.Replace, "Retira multitiplos espaços em branco");

            // --- Mask ------------------------
            Component comp3 = new Component(ReplaceInternalComponents.Mask, ComponentType.Replace, "Renomeia um arquivo com base em uma máscara");
            comp3.SetParameter(1, ComponentParameterType.String, "Máscara");

            Engine.Components.Add(comp2);
        }

        /// Executa um script específico sobre uma string
        private ScriptReturn RunInternalScript(ref string str, Script script)
        {
            string strOld = str;
            ScriptReturn ret = ScriptReturn.None;
            ReplaceInternalComponents ric = (ReplaceInternalComponents)Enum.Parse(typeof(ReplaceInternalComponents), script.ComponentId, true);

            try
            {
                switch (ric)
                {
                    // Remove Espaços                        
                    case ReplaceInternalComponents.RemoveSpaces:
                        {
                            str = Regex.Replace(str, @"\s+", " ");
                            break;
                        }

                    // Remove Espaços                        
                    case ReplaceInternalComponents.RegExp:
                        {
                            RegexOptions reo = RegexOptions.None;
                            if (script.Parameters[3].GetBoolValue()) { reo = RegexOptions.IgnoreCase; }

                            str = Regex.Replace(str, script.Parameters[1].Value, script.Parameters[2].Value, reo);
                            break;
                        }

                    // Substitui uma lista de trechos (par1) por um trecho específico(par2)
                    case ReplaceInternalComponents.SimpleReplace:
                        {
                            string pattern = string.Empty;
                            string substr;
                            RegexOptions reo = RegexOptions.None;

                            if (script.Parameters[3].GetBoolValue())
                            {
                                reo = RegexOptions.IgnoreCase;
                            }

                            for (int i = 0; i < script.Parameters[1].Value.Split('|').Length; i++)
                            {
                                if (pattern != string.Empty) { pattern = pattern + "|"; }
                                substr = script.Parameters[1].Value.Split('|')[i];
                                if (substr == "." || substr == "-" || substr == "*" || substr == "(" || substr == ")") substr = @"\" + substr;

                                pattern += "(" + substr + ")";
                            }

                            str = Regex.Replace(str, pattern, script.Parameters[2].Value, reo);
                            break;
                        }

                    case ReplaceInternalComponents.Mask:
                        {
                            Regex mask = new Regex(script.Parameters[1].Value.Replace(".", "[.]").Replace("*", ".*").Replace("?", "."));
                            //str = Regex.Replace(str, mask, "");
                            //return mask.IsMatch(sFileName);
                            break;
                        }
                }

                ret = ScriptReturn.Success;
            }
            catch
            {
                Engine.Messages.AddInternalError("ReplaceEngine.RunInternalScript." + ric.ToString());
                str = strOld;
                ret = ScriptReturn.Error;
            }

            return ret;
        }

        public ScriptReturn RunScripts(ref string str, List<Script> Scripts)
        {
            ScriptReturn ret = ScriptReturn.None;

            foreach (Script s in Scripts)
            {
                if (s.ComponentType == ComponentType.Replace)
                {
                    switch (s.Type)
                    {
                        case ScriptType.Internal:
                            {
                                ret = RunInternalScript(ref str, s);
                                break;
                            }
                        case ScriptType.Lua:
                            {
                                // Executa script LUA
                                break;
                            }
                        case ScriptType.Regexp:
                            {
                                // Executa script de Expressão Regular
                                break;
                            }
                    }
                }
            }

            return ret;
        }
    }
}
